package com.web3.management.security;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.experimental.UtilityClass;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Base64;
import java.util.Objects;

/**
 * 客户端Token工具类
 */
@Slf4j
@UtilityClass
public class AccountClientTokenUtils {

    private static final String TOKEN_PREFIX = "acct";
    private static final SecureRandom RANDOM = new SecureRandom();

    public String generateRawKey() {
        byte[] bytes = new byte[32];
        RANDOM.nextBytes(bytes);
        return Base64.getUrlEncoder().withoutPadding().encodeToString(bytes);
    }

    public String buildToken(Integer accountId, String rawKey) {
        return TOKEN_PREFIX + "-" + accountId + "-" + rawKey;
    }

    public boolean isAccountClientToken(String token) {
        return StringUtils.hasText(token) && token.startsWith(TOKEN_PREFIX + "-");
    }

    public ParsedToken parseToken(String token) {
        if (!isAccountClientToken(token)) {
            return null;
        }
        String[] parts = token.split("-", 3);
        if (parts.length != 3) {
            return null;
        }
        try {
            Integer accountId = Integer.valueOf(parts[1]);
            String rawKey = parts[2];
            if (!StringUtils.hasText(rawKey)) {
                return null;
            }
            return new ParsedToken(accountId, rawKey);
        } catch (NumberFormatException ex) {
            log.warn("解析客户端Token失败: {}", token);
            return null;
        }
    }

    public String hashRawKey(String rawKey) {
        Objects.requireNonNull(rawKey, "rawKey");
        try {
            MessageDigest digest = MessageDigest.getInstance("SHA-256");
            byte[] bytes = digest.digest(rawKey.getBytes(StandardCharsets.UTF_8));
            return Base64.getEncoder().encodeToString(bytes);
        } catch (NoSuchAlgorithmException e) {
            throw new IllegalStateException("SHA-256算法不可用", e);
        }
    }

    @Data
    @AllArgsConstructor
    public static class ParsedToken {
        private Integer accountId;
        private String rawKey;
    }
}
